#ifndef GameMain_H
#define GameMain_H

#include "GLAllInOne.h"
#include "Mesh.h"
#include "Texture.h"
#include "Shader.h"
#include "GameObject.h"
#include "Transform.h"
#include "SystemBase.h"
#include "Scene.h"
#include "Renderer.h"
#include "Camera.h"
#include "Application.h"
#include <iostream>

using namespace glm;
namespace ManchyGL
{
	class GameMain :public SystemBase
	{
	private:
		float mixValue = 0.2f;
		float MIX_DELTA = 0.005f;

		Mesh* _mesh;
		Texture* _texture1;
		Texture* _texture2;
		Shader* _shader;
		
		Camera* _camera;
		GameObject* _go;
	public:
		void OnCreate(Application* application)
		{
			this->SystemBase::OnCreate(application);
			application->SetTitle("LearnOpenGL");
			application->SetBgColor(0.2f, 0.3f, 0.3f, 1.0f);
		}

		void OnAwake(Application* application)
		{
			_shader = new Shader("texture.vs", "texture.fs");

			float vertices[] = {
			-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
			 0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
			 0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
			 0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
			-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
			-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

			-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
			 0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
			 0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
			 0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
			-0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
			-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

			-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
			-0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
			-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
			-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
			-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
			-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

			 0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
			 0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
			 0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
			 0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
			 0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
			 0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

			-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
			 0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
			 0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
			 0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
			-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
			-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

			-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
			 0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
			 0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
			 0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
			-0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
			-0.5f,  0.5f, -0.5f,  0.0f, 1.0f
			};
			_mesh = new Mesh();
			_mesh->SetVertexData(vertices, sizeof(vertices), NULL, 0);
			
			_texture1 = new Texture();
			_texture1->Load("media/container.jpg");

			_texture2 = new Texture();
			_texture2->Load("media/awesomeface.jpg");

			_camera = application->GetCamera();
			_camera->GetTransform()->SetPosition(vec3(0.0f,0.0f,3.0f));

			GameObject* go = application->GetScene()->NewGameObject("Cube");
			Renderer* r = go->GetRenderer();
			r->mesh = _mesh;
			r->texture1 = _texture1;
			r->texture2 = _texture2;
			r->shader = _shader;
			go->GetTransform()->SetPosition(vec3(1.0f,0.0f,0.0f));
			_go = go;

			go = application->GetScene()->NewGameObject("Cube2");
			r = go->GetRenderer();
			r->mesh = _mesh;
			r->texture1 = _texture1;
			r->texture2 = _texture2;
			r->shader = _shader;
			go->GetTransform()->SetPosition(vec3(-1.0f, 0.0f, 0.0f));
		}

		void OnUpdate(float time, float deltaTime)
		{
			GLFWwindow* wnd = GetAppliation()->GetWindow();
			float speed = 0.2f;

			Transform* tr = _go->GetTransform();
			vec3 position = tr->GetPosition();
			vec3 rotation = tr->GetRotation();
			tr->SetRotation(vec3(rotation.x, rotation.y+speed, rotation.z));

			tr = _camera->GetTransform();
			position = tr->GetPosition();
			rotation = tr->GetRotation();

			if (glfwGetKey(wnd, GLFW_KEY_W) == GLFW_PRESS)
			{
				position -= speed * tr->GetForward();
			}

			if (glfwGetKey(wnd, GLFW_KEY_S) == GLFW_PRESS)
			{
				position += speed * tr->GetForward();
			}

			if (glfwGetKey(wnd, GLFW_KEY_A) == GLFW_PRESS)
			{
				position -= speed * tr->GetRight();
			}

			if (glfwGetKey(wnd, GLFW_KEY_D) == GLFW_PRESS)
			{
				position += speed * tr->GetRight();
			}

			if (glfwGetKey(wnd, GLFW_KEY_Q) == GLFW_PRESS)
			{
				position += speed * tr->GetUp();
			}

			if (glfwGetKey(wnd, GLFW_KEY_E) == GLFW_PRESS)
			{
				position -= speed * tr->GetUp();
			}

			if (glfwGetKey(wnd, GLFW_KEY_LEFT) == GLFW_PRESS)
			{
				rotation.y += speed;
			}

			if (glfwGetKey(wnd, GLFW_KEY_RIGHT) == GLFW_PRESS)
			{
				rotation.y -= speed;
			}

			if (glfwGetKey(wnd, GLFW_KEY_UP) == GLFW_PRESS)
			{
				rotation.x += speed;
			}

			if (glfwGetKey(wnd, GLFW_KEY_DOWN) == GLFW_PRESS)
			{
				rotation.x -= speed;
			}
			
			tr->SetPosition(position);
			tr->SetRotation(rotation);
		}

		void OnRender()
		{
			Application* app = this->GetAppliation();
			Scene* scene = app->GetScene();

			float aspectRatio = (float)app->GetWidth() / (float)app->GetHeight();
			_camera->SetAspect(aspectRatio);

			int len = scene->GetCount();
			for (int i = 0; i < len; ++i)
			{
				GameObject* go = scene->GetGameObject(i);
				Renderer* r = go->GetRenderer();
				if (NULL != r)
					r->Render(_camera);
			}
		}
	};
}
#endif